package com.mtbu.comm;

import my.tool.ConfigProp;
import my.tool.ConfigUtil;
import my.myproperties.tool.PropertyLoadCaller;

import java.io.FileInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.text.SimpleDateFormat;

/**
 * myproperties的工具类，通过该类访问属性文件中的属性
 *
 * @author Skeven Huang
 * @version 1.0
 */
public class PropUtil {

    private static PropertyLoadCaller onloadCaller = null;
    private static Map<String, Properties> propsM = new HashMap<String, Properties>();
    public static List<DynamicPropReloader> listPropReloader=new ArrayList<DynamicPropReloader>();

    static {
        String files = ConfigProp.getProperties("my.property.files");
        String proponlad = ConfigProp.getProperties("my.property.onloader");
        try {
            if(PropUtil.getPropertyLoadCaller() == null && proponlad != null && !proponlad.trim().equals("")) {
                PropUtil.setPropertyLoadCaller((PropertyLoadCaller) Class.forName(proponlad.trim()).newInstance());
            }
        } catch(Exception ex) {
            ex.printStackTrace();
        }
        if(files != null && !files.trim().equals("")) {
            try {
                //获取类路径
                String classpath = ConfigUtil.getConstantPath();
                String[] propFiles = files.trim().split(",");
                for(int i = 0; i < propFiles.length; i++) {
                    String[] config = propFiles[i].trim().split(":");
                    long inteval = 0;
                    if(config.length > 1) {
                        inteval = new Long(config[1]);
                    }
                    PropUtil.loadProperties(classpath + config[0]);
                    if(inteval > 0) {
                        DynamicPropReloader propReloader=new DynamicPropReloader(classpath + config[0], inteval);
                        propReloader.setDaemon(true);
                        listPropReloader.add(propReloader);
                        propReloader.start();
                    }
                }
                System.out.println("****************** init properties ... ok ******************");
            } catch(Exception ex) {
                ex.printStackTrace();
                System.out.println("****************** init properties error!!!");
            }
        }

        //将src下的properties文件同步到classes下，用于开发阶段
        try {
            if(PropUtil.getInstance("constant").getProperty("com.src.sync", "").equals("1")) {
                File srcDir = new File(PropUtil.getInstance("constant").getProperty("com.src.path", ""));
                if(srcDir != null && srcDir.exists() && srcDir.isDirectory()) {
                    new srcSyncer(srcDir, PropUtil.getInstance("constant").getProperty("com.src.inteval", "1000")).start();
                }
            }
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void releasePropReloader(){
        for(DynamicPropReloader propReloader:listPropReloader){
            propReloader.setNeedExit(true);
            try {
                synchronized(propReloader.lock){
                    propReloader.lock.notify();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    protected static void setPropertyLoadCaller(PropertyLoadCaller onloadCaller) {
        PropUtil.onloadCaller = onloadCaller;
    }

    protected static PropertyLoadCaller getPropertyLoadCaller() {
        return onloadCaller;
    }

    public static void loadProperties(String filePath) throws Exception {
        Properties properties = new Properties();
        File file = new File(filePath);
        FileInputStream fi = new FileInputStream(file);
        properties.load(fi);
        fi.close();
        propsM.put(file.getName(), properties);
        Constant.init();
        if(onloadCaller != null) {
            onloadCaller.onLoad(file.getName());
        }

    }

    /**
     * 获取指定文件名所对应的properties对象
     *
     * @param fileName 属性文件名，不带扩展名。如对于constant.properties，这里的fileName=constant
     * @return
     */
    public static Properties getInstance(String fileName) {
        if(!propsM.containsKey(fileName + ".properties")) {
            return new Properties();
        }
        return propsM.get(fileName + ".properties");
    }

    public static void setInstance(String fileName, Properties prop) {
        propsM.put(fileName + ".properties", prop);
    }

    public String getPropertyString(String s) {
        String value = getInstance("constant").getProperty(s);
        if(value == null) return "";
        return value.trim();
    }

    public int getPropertyInt(String s) {
        String value = getPropertyString(s);
        int rt = 0;
        try {
            rt = new Integer(value);
        } catch(Exception ex) {
            rt = 0;
        }
        return rt;
    }

    public short getPropertyShort(String s) {
        String value = getPropertyString(s);
        short rt = 0;
        try {
            rt = new Short(value);
        } catch(Exception ex) {
            rt = 0;
        }
        return rt;
    }

    public long getPropertyLong(String s) {
        String value = getPropertyString(s);
        long rt = 0;
        try {
            rt = new Long(value);
        } catch(Exception ex) {
            rt = 0;
        }
        return rt;
    }

    public float getPropertyFloat(String s) {
        String value = getPropertyString(s);
        float rt = 0;
        try {
            rt = new Float(value);
        } catch(Exception ex) {
            rt = 0;
        }
        return rt;
    }

    public double getPropertyDouble(String s) {
        String value = getPropertyString(s);
        double rt = 0;
        try {
            rt = new Double(value);
        } catch(Exception ex) {
            rt = 0;
        }
        return rt;
    }

    public byte getPropertyByte(String s) {
        String value = getPropertyString(s);
        byte rt = 0;
        try {
            rt = new Byte(value);
        } catch(Exception ex) {
            rt = 0;
        }
        return rt;
    }

    public boolean getPropertyBoolean(String s) {
        String value = getPropertyString(s);
        boolean rt = false;
        try {
            rt = new Boolean(value);
        } catch(Exception ex) {
            rt = false;
        }
        return rt;
    }

    public Date getPropertyDate(String s) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        String value = getPropertyString(s);
        if(value.equals("")) return null;
        if(value.indexOf(" ") <= -1) {//只有日期或时间
            if(value.indexOf("-") > -1) {//日期
                value += " 00:00:00";
            } else if(value.indexOf(":") > -1) {//时间
                value = "1970-01-01 " + value;
            } else {
                return null;
            }
        }
        Date rt = null;
        try {
            rt = formatter.parse(value);
        } catch(Exception ex) {
            rt = null;
        }
        return rt;
    }


    private static class DynamicPropReloader extends Thread {
        private String filePath = null;
        private long inteval = 10 * 60 * 1000;
        private long lastModifyTime = 0;
        private boolean needExit=false;
        private final Object lock = new Object();

        public DynamicPropReloader(String filePath, long inteval) {
            this.filePath = filePath;
            this.inteval = inteval;
        }

        public boolean isNeedExit() {
            return needExit;
        }

        public void setNeedExit(boolean needExit) {
            this.needExit = needExit;
        }

        public void run() {
            while(!needExit) {
                try {
                    File file = new File(filePath);
                    long begin = System.currentTimeMillis();
                    if(file.lastModified() <= lastModifyTime) {
                    } else {
                        PropUtil.loadProperties(filePath);
                        lastModifyTime = file.lastModified();

                        System.out.println("");
                        System.out.println("DynamicPropReloader:#######" + file.getName() + " Reload OK,use " + (System.currentTimeMillis() - begin) + "ms #######");
                        System.out.println("");
                    }
                    synchronized(lock) {
                        lock.wait(inteval);
                    }
                } catch(Exception ex) {
                    ex.printStackTrace();
                    System.out.println("**************** " + filePath + ":error!");
                }
            }
            System.out.println("DynamicPropReloader...Exit!");
        }


    }

    private static class srcSyncer extends Thread {
        private File srcDir = null;
        private long inteval = 1000;
        private Object lock = new Object();

        public srcSyncer(File srcDir, String intevalstr) {
            this.srcDir = srcDir;
            try {
                inteval = Long.parseLong(intevalstr);
            } catch(Exception ex) {
                inteval = 1000;
            }
            if(inteval <= 0) {
                inteval = 1000;
            }
        }

        public void run() {
            while(true) {
                try {
                    String exts = PropUtil.getInstance("constant").getProperty("com.src.ext", ".properties");
                    List<File> propfiles = new LinkedList<File>();
                    File[] subfiles = srcDir.listFiles();
                    for(int i = 0; i < subfiles.length; i++) {
                        int index = subfiles[i].getName().lastIndexOf(".");
                        if(index <= -1) continue;
                        String ext = subfiles[i].getName().substring(index);
                        if(exts.indexOf(ext) > -1 || subfiles[i].getName().endsWith(".properties")) {
                            propfiles.add(subfiles[i]);
                        }
                    }
                    for(int i = 0; i < propfiles.size(); i++) {
                        File srcFile = propfiles.get(i);
                        File classFile = new File(ConfigUtil.getConstantPath() + srcFile.getName());
                        if(classFile == null || !classFile.exists() || !classFile.isFile() || srcFile.lastModified() > classFile.lastModified()) {
                            FileOutputStream fos = new FileOutputStream(classFile);
                            FileInputStream fis = new FileInputStream(srcFile);
                            byte[] buffer = new byte[1024];
                            int r = fis.read(buffer);
                            while(r > -1) {
                                fos.write(buffer, 0, r);
                                r = fis.read(buffer);
                            }
                            fos.close();
                            fis.close();
                            System.out.println("####srcSyncer:src file is synced:" + srcFile.getName());
                        }
                    }
                    synchronized(lock) {
                        lock.wait(inteval);
                    }
                } catch(Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}
